// InternetDll.cpp : Defines the entry point for the DLL application.
//

#include <objbase.h>
#include <initguid.h>
#include <tlhelp32.h>
#include <toolhelp.h>
#include "InternetDll.h"


BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
					 )
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
    return TRUE;
}
//------------------------------------------------------------------------------------------------

INTERNETDLL_API DWORD GetInternetFileSize(HINTERNET hRequest)
{
	DWORD dwret;
	TCHAR dwfilesizeStr[64];
	
	DWORD dwbuflen=sizeof(dwfilesizeStr),dwindex=0;
	memset(dwfilesizeStr,0,sizeof(dwfilesizeStr));
	if(!HttpQueryInfo(hRequest,HTTP_QUERY_CONTENT_LENGTH ,dwfilesizeStr,&dwbuflen,&dwindex))
	{
		dwret=GetLastError();
		return 0;
	}
	else
	{
		//DebugBreak();
		return _wtoi(dwfilesizeStr);
	}
	
}
//------------------------------------------------------------------------------------------------
INTERNETDLL_API DWORD SetInternetFileRange(HINTERNET hRequest,DWORD start,DWORD end)
{
	DWORD dwret;
	TCHAR szStr[500];
	DWORD dwbuflen=sizeof(szStr),dwindex=0;

	memset(szStr,0,sizeof(szStr)); 
#if 0
	HttpQueryInfo(hRequest,HTTP_QUERY_RAW_HEADERS_CRLF,szStr,&dwbuflen,&dwindex);
#endif
	if(!HttpQueryInfo(hRequest,HTTP_QUERY_CONTENT_RANGE,szStr,&dwbuflen,&dwindex))
	{
		dwret=GetLastError();
		return 0;
	}
	return TRUE;
}

//------------------------------------------------------------------------------------------------
INTERNETDLL_API DWORD CloseInternet(HANDLE hConnection)
{
	ConnMgrReleaseConnection(hConnection,0);
	return FALSE;
}

INTERNETDLL_API DWORD ConnectToInternet(HANDLE *phConnection)
{
	DWORD dwStatus;
	//CONNMGR_DESTINATION_INFO Info;
	CONNMGR_CONNECTIONINFO sConInfo;
#if 0
	DWORD i;

	i=0;
	while(S_OK==ConnMgrEnumDestinations(i,&Info))
	{
		++i;
		DebugBreak();
	}
#endif
	//try to connect to internet
	memset(&sConInfo,0, sizeof(CONNMGR_CONNECTIONINFO));
	sConInfo.cbSize=sizeof(CONNMGR_CONNECTIONINFO);
	sConInfo.dwParams=CONNMGR_PARAM_GUIDDESTNET;
	sConInfo.dwPriority=CONNMGR_PRIORITY_USERINTERACTIVE;
	sConInfo.dwFlags=0;
	sConInfo.bExclusive=FALSE;
	sConInfo.bDisabled=FALSE;
	sConInfo.guidDestNet=IID_DestNetCorp;

	if (ConnMgrEstablishConnectionSync(&sConInfo,phConnection,60000,&dwStatus)==S_OK)
	{
		if(dwStatus==CONNMGR_STATUS_CONNECTED)
			return TRUE;
	}
#if 0
	if(S_OK==ConnMgrConnectionStatus(&hConnection,&dwStatus))
	{
		if(dwStatus!=CONNMGR_STATUS_CONNECTED)
		{
			;
		}
	}
#endif
	return FALSE;
}

// ------------------------ DEVICE ID MANAGEMENT ------------------------

static BOOL
HexStringToDword(LPCWSTR FAR& lpsz, DWORD FAR& Value,
                 int cDigits, WCHAR chDelim)
{
	int Count;

	Value = 0;
	for (Count = 0; Count < cDigits; Count++, lpsz++)
	{
		if (*lpsz >= '0' && *lpsz <= '9')
			Value = (Value << 4) + *lpsz - '0';
		else if (*lpsz >= 'A' && *lpsz <= 'F')
			Value = (Value << 4) + *lpsz - 'A' + 10;
		else if (*lpsz >= 'a' && *lpsz <= 'f')
			Value = (Value << 4) + *lpsz - 'a' + 10;
		else
			return(FALSE);
	}

	if (chDelim != 0)
		return *lpsz++ == chDelim;
	else
		return TRUE;
}


static BOOL
wUUIDFromString(LPCWSTR lpsz, LPGUID pguid)
{
	DWORD dw;

	if (!HexStringToDword(lpsz, pguid->Data1, sizeof(DWORD)*2, '-'))
		return FALSE;

	if (!HexStringToDword(lpsz, dw, sizeof(WORD)*2, '-'))
		return FALSE;

	pguid->Data2 = (WORD)dw;

	if (!HexStringToDword(lpsz, dw, sizeof(WORD)*2, '-'))
		return FALSE;

	pguid->Data3 = (WORD)dw;

	if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
		return FALSE;

	pguid->Data4[0] = (BYTE)dw;

	if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, '-'))
		return FALSE;

	pguid->Data4[1] = (BYTE)dw;

	if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
		return FALSE;

	pguid->Data4[2] = (BYTE)dw;

	if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
		return FALSE;

	pguid->Data4[3] = (BYTE)dw;

	if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
		return FALSE;

	pguid->Data4[4] = (BYTE)dw;

	if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
		return FALSE;

	pguid->Data4[5] = (BYTE)dw;

	if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
		return FALSE;

	pguid->Data4[6] = (BYTE)dw;
	if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
		return FALSE;

	pguid->Data4[7] = (BYTE)dw;

	return TRUE;
}

static BOOL
GUIDFromString(LPCWSTR lpsz, LPGUID pguid)
{
	if (*lpsz++ != '{' )
		return FALSE;

	if(wUUIDFromString(lpsz, pguid) != TRUE)
		return FALSE;

	lpsz +=36;

	if (*lpsz++ != '}' )
		return FALSE;

	return TRUE;
}

// this routine converts a text string to a GUID if possible.
INTERNETDLL_API BOOL ConvertStringToGuid (LPCTSTR pszGuid, GUID *pGuid)
{
	BOOL fOk = FALSE;
	TCHAR txt[512];

	//DEBUGCHK(pGuid != NULL && pszGuid != NULL);

	if (! GUIDFromString(pszGuid, pGuid))
	{
		wsprintf(txt,_T("couldn't parse '%s'\r\n"),pszGuid);
		MessageBox(0, txt,_T("error"),MB_ICONEXCLAMATION|MB_TOPMOST);
	}
	fOk = TRUE;

	return fOk;
}
INTERNETDLL_API BOOL ConvertGuidToString(PWSTR szBuf, DWORD bufsize,GUID *pClass)
{
	return StringCchPrintf(szBuf, bufsize,_T("%08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X"), 
						pClass->Data1, pClass->Data2, pClass->Data3,
						(pClass->Data4[0] << 8) + pClass->Data4[1], pClass->Data4[2], pClass->Data4[3], 
						pClass->Data4[4], pClass->Data4[5], pClass->Data4[6], pClass->Data4[7]);
}
//------------------------------------------------------------------------------------------------------
INTERNETDLL_API unsigned int GetCurrentProcessBase()
{
	PROCESSENTRY32 processinfo;
	HANDLE hndSnap;
	DWORD CurId;
	unsigned int CurBase=0;

	CurId=GetCurrentProcessId();
	hndSnap=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
	if(INVALID_HANDLE_VALUE!=hndSnap)
	{
		processinfo.dwSize=sizeof(PROCESSENTRY32);
		if(Process32First(hndSnap,&processinfo))
		{
			do
			{
				if(processinfo.th32ProcessID==CurId)
				{
					//current process is found
					CurBase=processinfo.th32MemoryBase;
					break;
				}
			}while(Process32Next(hndSnap,&processinfo));
		}
		//close system snap
		CloseToolhelp32Snapshot(hndSnap);
	}
	return CurBase;
}
//------------------------------------------------------------------------------------------------------
INTERNETDLL_API DWORD RegDeviceDriverFlags(LPCWSTR szKeyPath, DWORD flags,BOOL blset)
{
    BOOL rc = 0;
    HKEY hKey;
    DWORD value;
	DWORD type=REG_DWORD,ret=0;
	DWORD val;

    // Open/create key
    if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, szKeyPath, 0, NULL, 0, 0, NULL,&hKey, &value) != ERROR_SUCCESS) 
		 goto cleanUp;

    // Get value
	ret=sizeof(val);
    if(RegQueryValueEx (hKey, L"Flags", 0, &type, (UCHAR*)&val, &ret) != ERROR_SUCCESS)
		goto cleanUp;

	//check
	if(blset)
		val|=flags;
	else
		val&=(~flags);

    // Set value
    rc = RegSetValueEx(
        hKey, L"Flags", 0, REG_DWORD, (UCHAR*)&val, sizeof(DWORD)
    ) == ERROR_SUCCESS;

	RegFlushKey(hKey);

    // Close key
    RegCloseKey(hKey);

cleanUp:
    return rc;
}
//------------------------------------------------------------------------------------------------------
INTERNETDLL_API BOOL RegDelDeviceDriver(LPCWSTR szKeyPath)
{
    BOOL rc = 0;
    HKEY hKey;
    DWORD value;


    // Open/create key
    if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, szKeyPath, 0, NULL, 0, 0, NULL,
         &hKey, &value) != ERROR_SUCCESS) 
		 goto cleanUp;

    // Delete value
	RegDeleteKey(hKey,szKeyPath);

	RegFlushKey(hKey);

    // Close key
    RegCloseKey(hKey);

cleanUp:
    return rc;
}
//------------------------------------------------------------------------------------------------------
INTERNETDLL_API BOOL RegGetDeviceModuleName(TCHAR * szDeviceKey,TCHAR * ModuleName,DWORD len)
{
	HKEY hk;
	DWORD dwStatus,cbVal=len,dwType;
	BOOL ret=FALSE;

	dwStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szDeviceKey, 0, 0, &hk);
	if(dwStatus == ERROR_SUCCESS) 
	{
		dwType=REG_SZ;
		if(ModuleName)
		{
			dwStatus=RegQueryValueEx(hk,_T("Dll"),NULL,&dwType,(LPBYTE)ModuleName,&cbVal);
			if(dwStatus == ERROR_SUCCESS) 
			{
				ret=TRUE;
			}
		}
		RegCloseKey(hk);
	}
	return ret;
}


INTERNETDLL_API void InstallCabFile(LPCTSTR pCabFileName)
{
	PROCESS_INFORMATION ECallProcessInfo;
	TCHAR cmd[200];

	wsprintf(cmd,_T(" /delete 1 \\%s "),pCabFileName);
	CreateProcess(TEXT("\\Windows\\Wceload.exe"),cmd, NULL, NULL, FALSE,
	              INHERIT_CALLER_PRIORITY,NULL, NULL, NULL,&ECallProcessInfo);
}

static DWORD IsValidVersion(TCHAR c)
{
	TCHAR match[]=_T("0123456789");
	TCHAR *p,*pm;
	if(c==0)
		return 0;
	else if(c==_T('.'))
		return 2;
	pm=match;
	pm+=(sizeof(match)/sizeof(match[0]));

	for(p=match;p<pm && *p!=0;p++)
	{
		if(*p==c)
			return 1;
	}
	return 0;
}
static DWORD ParseVersion(LPTSTR buf,DWORD size,TCHAR ** pVal)
{
	DWORD i,sum,version=0,ret;
	TCHAR * p;

	*pVal=NULL;

	for(i=0,sum=0,p=buf;i<size;i++,p++)
	{
		ret=IsValidVersion(*p);
		if(ret)
		{
			if(sum>=2)
			{
				*pVal=p;
				return TRUE;
			}
			else if(ret==2)
			{
				sum++;
			}
		}
		else
			return FALSE;
	}
	return FALSE;
}

INTERNETDLL_API DWORD VersionStringToDword(LPTSTR buf,DWORD size)
{
	TCHAR *pVer;
	if(ParseVersion(buf,size,&pVer))
	{
		return _wtoi(pVer);
	}
	else
		return 0;
}